
// Object.assign();


// const test1 = {
//   a: 1,
//   b: 2
// }

// const test2 = {
//   b: 3,
//   c: 4
// }

// const test3 = {
//   c: 5,
//   d: 6
// }
// test3.__proto__.e = 99;
// 其实相当于在
// Object.prototype.e = 99;

// function Test3 (){
//   this.c = 5;
//   this.d = 6;
// }
// const test3 = new Test3();
// test3.__proto__.e = 99;

// const test4 = Object.assign(test1, test2, test3);

// console.log(test1);
// console.log(test2);
// console.log(test3);
// console.log(test4);

// console.log(test4 === test1); // true 第一个参数与返回的对象的引用地址一样

// const v1 = 123;
// const v2 = '123';
// const v3 = true;
// const v4 = function test() {};

// const v5 = Object.assign({}, v1, null, v2, undefined, v3, v4);
// console.log(v5); // { "0": "a", "1": "b", "2": "c" }

// console.log(new Number(v1));
// console.log(new String(v2));
// console.log(new Boolean(v3));
// console.log(new Function(v4));

// const target = Object.defineProperty({}, 'a', {
//   value: 1,
//   writable: true,
  // enumerable: true,
  // configurable: true
// })

// console.log(target); // 浏览器的机制 可以查看
// Object.assign(target, {b: 2}, {b: 3, c: 4}, {a: 2, d: 5});

// console.log(target); //TypeError: Cannot assign to read only property 'a' of object
// console.log(target.b);
// console.log(target.c);
// console.log(target.a);
// console.log(target.d);

// for (let k in target) {
//   console.log(k, target[k]);
// }

const source = {
  a: 1,
  get b () { // 访问器
    return 2;
  }
}

// console.log(source);
// const res = Object.assign({}, source);
// // 访问器拷贝不了
// console.log(res);


// 实现assign 拷贝访问器(属性定义)
Object.myAssign = function (target, ...sources) {
  sources.forEach(source => {
    const descriptors = Object.keys(source).reduce((descriptors, key) => {
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
      return descriptors;
    }, {})
    Object.defineProperties(target, descriptors);
  });
  return target;
}

const res2 = Object.myAssign({}, source);
console.log(res2)


/**
 * Object.assign(target, ...sources)
 * target: 目标对象 sources: 源对象
 * 用于将所有 可枚举属性的值(!!!) 从一个或多个源对象 分配到目标对象。返回目标对象。
 * 
 * 如果目标对象中的属性具有相同的键，则属性将被源对象中的属性覆盖
 * 后面的源对象的属性将类似地覆盖前面的源对象的属性。
 * 
 * 会拷贝源对象自身的并且可枚举的属性到目标对象(浅拷贝)
 * 
 * 继承属性(原型属性)和不可枚举属性是不能拷贝的
 * 
 * 源对象是原始类型会被包装为对象，null 和 undefined 会被忽略
 * 只有字符串的包装对象才可能有自身可枚举属性
 * 
 * 如果出现异常(只读)会打断后续拷贝任务
 * 
*/
